﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Joy.Erp.Ufida.Core;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Caching;

namespace Joy.Erp.Ufida.Asns
{
    public class ASNUfidaAppService : UfidaAppService, IASNUfidaAppService
    {
        private readonly IMemoryCache _memoryCache;
        protected ITokenUfidaAppService TokenUfidaAppService =>
            LazyServiceProvider.LazyGetRequiredService<ITokenUfidaAppService>();

        public ASNUfidaAppService(IMemoryCache memoryCache)
        {
            _memoryCache = memoryCache;
        }

        public async Task<ASNUfidaDto> GetLineAsync(long lineid, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.FirstOrDefault(x => x.ID == lineid);
        }

        public async Task<List<ASNUfidaDto>> GetLinesAsync(long id, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.Where(x => x.ID == id).ToList();
        }

        public async Task<ASNUfidaDto> FindByDocNoAsync(string docNo, DateTime start, DateTime end)
        {
            var u9list = await GetAllAsync(start, end);
            return u9list.FirstOrDefault(x => x.DocNo == docNo);
        }

        public async Task<List<ASNUfidaDto>> GetAllAsync(DateTime start, DateTime end)
        {
            var cacheKey = $"{typeof(ASNUfidaAppService).FullName}|{start:yyyyMMdd}|{end:yyyyMMdd}";
            if (!_memoryCache.TryGetValue(cacheKey, out List<ASNUfidaDto> cachedData))
            {
                cachedData = await GetAllFromApiAsync(start, end);
                _memoryCache.Set(
                    cacheKey,
                    cachedData,
                    new MemoryCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(30),
                        Size = cachedData.Count,
                    }
                );
            }
            return cachedData;
        }

        private async Task<List<ASNUfidaDto>> GetAllFromApiAsync(DateTime start, DateTime end)
        {
            var token = await TokenUfidaAppService.GetTokenAsync();
            var queryUrl = TokenUfidaAppService.U9ApiConfig.BaseUrl.AppendSegments(
                $"webapi/QueryCommon/QueryInfoBySql"
            );

            var httpRequest = new HttpRequestMessage(HttpMethod.Post, queryUrl);
            httpRequest.Headers.Add("token", token);

            var sqlBuilder = new StringBuilder();
            sqlBuilder.Append("select ");
            sqlBuilder.Append("  'ASN' as TableName ");
            sqlBuilder.Append("  ,a.ID ");
            sqlBuilder.Append("  ,a.DocNo ");
            sqlBuilder.Append("  ,a.BusinessDate ");
            sqlBuilder.Append("  ,a.[Status] ");
            sqlBuilder.Append("  ,a.ASNDocType as DocumentType ");
            sqlBuilder.Append("  ,a.Supplier_Supplier as Supplier ");
            sqlBuilder.Append("  ,a.ShipContact ");
            sqlBuilder.Append("  ,a.TelNum ");
            sqlBuilder.Append("  ,a.CarNo ");
            sqlBuilder.Append("  ,a.ShipDate  ");
            sqlBuilder.Append("  ,a.PlanArriveDate ");
            sqlBuilder.Append("  ,atrl.Memo ");
            sqlBuilder.Append("  ,al.ID as LineID ");
            sqlBuilder.Append("  ,al.DocLineNo ");
            sqlBuilder.Append("  ,al.ItemInfo_ItemID as ItemMasterID ");
            sqlBuilder.Append("  ,al.ItemInfo_ItemCode as ItemCode ");
            sqlBuilder.Append("  ,al.ItemInfo_ItemName as ItemName ");
            sqlBuilder.Append("  ,al.ShipQtyTU as Quantity ");
            sqlBuilder.Append("  ,al.POQtyTU as PurchasingQuantity ");
            sqlBuilder.Append("  ,al.TotalRcvQtyTU as ReceivedQuantity ");
            sqlBuilder.Append("  ,al.TradeUOM ");
            sqlBuilder.Append("  ,a.CreatedOn ");
            sqlBuilder.Append("from PM_ASNLine al ");
            sqlBuilder.Append("  inner join PM_ASN a on a.ID = al.ASN ");
            sqlBuilder.Append("  inner join PM_ASN_Trl atrl on a.ID = atrl.ID and atrl.SysMLFlag='zh-CN' ");
            sqlBuilder.Append("  inner join Base_Organization o on o.ID = a.Org ");
            sqlBuilder.Append("where 1=1 ");
            sqlBuilder.Append($"  and a.CreatedOn >= '{start.ToString("yyyyMMdd")}' ");
            sqlBuilder.Append($"  and a.CreatedOn <= '{end.ToString("yyyyMMdd")}' ");
            sqlBuilder.Append($"  and o.Code = '{SourceConfig.OrgCode}' ");

            var jsonObj = new { SqlString = sqlBuilder.ToString() };
            var jsonObjStr = JsonConvert.SerializeObject(jsonObj);
            httpRequest.Content = new StringContent(jsonObjStr, Encoding.UTF8, "application/json");
            Logger.LogInformation($"开始请求Api接口，接口地址: {queryUrl}, 正文内容: {jsonObjStr}");

            var httpClient = new HttpClient();
            var response = await httpClient.SendAsync(httpRequest);
            response.HandStatusCode(queryUrl);

            var responseContent = await response.Content.ReadAsStringAsync();
            Logger.LogInformation($"开始解析Api返回结果");

            try
            {
                var resultObj = JsonConvert.DeserializeObject<CommonDto<ASNUfidaDto>>(
                    responseContent
                );
                if (!resultObj.Success)
                    throw new BusinessException("BasicArchives:104").WithData(
                        "ErrorMessage",
                        resultObj.ResMsg
                    );

                Logger.LogInformation($"Api接口请求成功，返回数据{resultObj.Data.Count}条");

                return resultObj.Data;
            }
            catch (JsonException ex)
            {
                throw new BusinessException("BasicArchives:103", innerException: ex).WithData(
                    "DtoType",
                    typeof(CommonDto).Name
                );
            }
        }
    }
}
